Основная часть работы будет осуществляться функцией
def sound2active(filename,shapekey='Pop out'):
try:
wr = wave.open(filename,'rb')
except wave.Error,e:
return popup(str(e)+'%t|Ok')
Затем мы делаем некоторые разумные проверки: мы сначала проверяем, является ли .wav-файл
c = wr.getnchannels()
if c!=1 : return popup('Only mono files are '+
'supported%t|Ok')
t = wr.getcomptype()
w = wr.getsampwidth()
if t!='NONE' or w!=2 :
return popup('Only 16-bit, uncompresses files '+
'are supported%t|Ok')
Теперь, когда мы можем работать с файлом, мы получаем его частоту дискретизации (frame rate, количество аудио сэмплов в секунду) и общее число байт (как ни странно, используя неуклюже названную функцию
fr= wr.getframerate()
n = wr.getnframes()
b = wr.readframes(n)
Наша следующая задача в том, чтобы получить контекст рендера у текущей сцены, чтобы извлечь количество видеокадров в секунду. Время в секундах нашей проигрываемой анимации будет определено длиной нашего аудио сэмпла, которое мы можем вычислить, разделив общее число аудио кадров в .wav-файле на количество аудио кадров в секунду (выделено в следующей части кода). Затем мы определяем константу
scn = Scene.GetCurrent()
context = scn.getRenderingContext()
seconds = float(n)/fr
sampleratio = fr/float(context.framesPerSec())
Как упомянуто раньше, модуль
samples = struct.unpack('<%dh'%n,b)
Теперь мы можем начать анимацию ключей формы. Мы получаем стартовый кадр из контекста рендера и вычисляем конечный кадр, умножая время в секундах в .wav-файле на частоту видеокадров. Заметьте, что он может оказаться дальше или ближе, чем конечный кадр, который мы можем получить из контекста рендера. Последний определяет конечный кадр, который будет отрендерен, когда пользователь нажмёт на кнопку Anim, но мы будем анимировать движение нашего активного объекта независимо от этой величины.