"""Add a low synthetic vocal moan at the hand emergence and export via VSE.""" import os, math, wave, array, random ROOT=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) OUT=os.path.join(ROOT,'preview','v4');random.seed(49) with wave.open(os.path.join(ROOT,'preview','effects.wav'),'rb') as w: rate=w.getframerate();samples=array.array('h',w.readframes(w.getnframes())) moan=[0.0]*len(samples);phase=0;filtered=0;start=13.04;length=3.15 for i in range(int(length*rate)): t=i/rate;pitch=92-25*(t/length)+2.2*math.sin(t*6.5) phase+=math.tau*pitch/rate # Harmonic vowel with resonances, descending pitch, and breath roughness. value=0 for h in range(1,15): freq=h*pitch;weight=.35*math.exp(-((freq-330)/160)**2)+.16*math.exp(-((freq-720)/210)**2) value+=weight*math.sin(h*phase)/math.sqrt(h) value+=.17*math.sin(phase)+.06*math.sin(phase*.5) filtered=.92*filtered+.08*random.uniform(-1,1) envelope=min(1,t/.16)*min(1,(length-t)/.65)*(.7+.3*math.sin(math.pi*t/length)) idx=int(start*rate)+i if idx=0:value+=gain*moan[index] mixed=old/32768+value output.append(int(max(-.98,min(.98,mixed))*32767)) assert max(abs(x) for x in output)<32767 path=os.path.join(OUT,'effects_with_groan.wav') with wave.open(path,'wb') as w:w.setparams((1,2,rate,len(output),'NONE','not compressed'));w.writeframes(array.array('h',output).tobytes()) print('GROAN: 13.04 to 16.19 seconds; peak',max(abs(x) for x in output)/32768) # When invoked with Blender, update a separate editable copy and export video. try:import bpy except ImportError:raise SystemExit(0) bpy.ops.wm.open_mainfile(filepath=os.path.join(OUT,'halloween_dark.blend')) s=bpy.context.scene for strip in list(s.sequence_editor.sequences): if strip.type=='SOUND':s.sequence_editor.sequences.remove(strip) s.sequence_editor.sequences.new_sound('Dark moan and ambience',path,channel=1,frame_start=1) bpy.ops.file.pack_all();bpy.ops.wm.save_as_mainfile(filepath=os.path.join(OUT,'halloween_dark_groan.blend')) # Reuse the already rendered movie; do not render the 3D scene again. bpy.ops.wm.read_factory_settings(use_empty=True);s=bpy.context.scene s.render.resolution_x=1280;s.render.resolution_y=720;s.render.resolution_percentage=100;s.render.fps=24;s.frame_start=1;s.frame_end=480 s.view_settings.view_transform='Standard';s.view_settings.look='Medium High Contrast' if False else 'None' s.sequence_editor_create();s.sequence_editor.sequences.new_movie('Existing rendered picture',os.path.join(OUT,'halloween_dark.mp4'),channel=1,frame_start=1) s.sequence_editor.sequences.new_sound('New mixed sound',path,channel=2,frame_start=1) s.render.image_settings.file_format='FFMPEG';s.render.ffmpeg.format='MPEG4';s.render.ffmpeg.codec='H264';s.render.ffmpeg.constant_rate_factor='HIGH';s.render.ffmpeg.audio_codec='AAC';s.render.ffmpeg.audio_bitrate=192 s.render.filepath=os.path.join(OUT,'halloween_dark_groan.mp4');bpy.ops.render.render(animation=True)