Создание эха в программе озвучивания

   В программе озвучивания ТРИО появились возможности реверберации. Немного изменилась и структура программы.

   СТРУКТУРА ПРОГРАММЫ ТРИО

   Собственно в тексте TRIO.bas находится фрагмент Дирижёр и три МУЗа - три процедуры MUZ1, MUZ2 и MUZ3, а также три подпрограммы-функции создания звука - FNSS1, FNSS2 FNSS3, каждая для своего МУЗа. И ещё маленькая подпрограмма создающая шапку звукового файла.
   И больше ничего. Это позволяет сосредоточиться на сценариях.

   Все же подпрограммы, к которым обращаются МУЗы и функции создания звука, отнесены в присоединяемый блок TRIO_FN.bas.

   Общая структура программы ТРИО такова -

TRIO.bas
   диалог Бейсика по поводу того, что делать
   фрагмент Дирижёр
   процедура MUZ1
   процедура MUZ2
   процедура MUZ3
     функция FNSS1
       сценарии
       коррекция параметров между периодами
       вычисления амплитуды основного звука
       аккордный повтор и сглаживание
       присоединение обертонов, обращение к ревербератору Rn()
     выход
     функция FNSS2
       сценарии
       коррекция параметров между периодами
       вычисления амплитуды основного звука
       аккордный повтор и сглаживание
       присоединение обертонов, обращение к ревербератору Rm()
     выход
     функция FNSS3
       сценарии
       коррекция параметров между периодами
       вычисления амплитуды основного звука
       аккордный повтор и сглаживание
       присоединение обертонов, обращение к ревербератору R()
      выход
    $INCLUDE "TRIO_FN.BAS" 'подключение блока функций
    подпрограмма создания шапки

  Как видим, аккордно повторяется на более высоких ступенях только основной звук, суммарный звук сглаживается, если сглаживание предусмотрено сценарием, и потом добавляются обертоны, относящиеся к основному звуку. Верхние звуки аккорда остаются без обертонов.

  Перед выходом из звуковой функции амплитуда звука отправляется на ревербератор (если он подключён). Об этом мы сейчас и поговорим.


   РЕВЕРБЕРАТОР. ФУНКЦИИ И ПОДКЛЮЧЕНИЕ.

  Ревербератора три. Они индивидуальны. Для каждого МУЗа со своим музыкальным инструментом ревербератор свой. Различаются и названия функций ревербераторов.
  Первая звуковая функция обращается к своему ревербератору так A=A+FNRn1(A,-1)
вторая - A=A+FNRm1(A,-1), а третья, без маленькой буквы - A=A+FNR1(A,-1)

  Ревербераторы большие, ёмкостью на 4800 семплов каждый. При скорости раздачи 32000 семплов в секунду, они имитируют эхо длительностью в 0.15 сек в помещении размером 25 метров - небольшой концертный зал. Кроме того имеется возможность поддержания многократного эха.
  Названия массивов ревербераторов соответствуют названиям функций - Rn(), Rm() и R().
  В остальном ревербераторы совершенно идентичны. В современном своём состоянии ревербератор подробно описан в статье http://www.proza.ru/2016/03/07/1229

  Чтобы ревербератор работал, отсылки к нему должны быть в сценарии. Посмотрим на сценарий звука аккордеона с эхом:

  CASE 7 'accordeon     tembr => Ar=1(0) 2 3
    MU2=0 : AU2=1 : DU2=30.999 : mod2=2
     MU3=0 : AU3=3 : DU3=30.999
    SELECT CASE ARE3 : CASE 0,1
    '>>>>="_1_2_3_4_5_6_7_8_9_0 _1_2_3_4_5_6_7_8_9_0_1_2_3_4"
    A31r$="50450145505050505050 5050505579555050504521455050" 'norm
    A32r$="50450145505050505050 5050505599555050504501455050" '-3 15 -21 L=24
    A33r$="50452145505050505050 5050505599555050504501455050" : CASE 2
    '>>>>="_1_2_3_4_5_6_7_8_9_0 _1_2_3_4_5_6_7_8_9_0_1_2_3_4"
    A31r$="50450101455050505050 5050505579795550505045212145" 'quiet
    A32r$="50450101455050505050 5050505599995550505045010145" '-3 15 -21 L=24
    A33r$="50452121455050505050 5050505599995550505045010145" : CASE 3
    '>>>>="_1_2_3_4_5_6_7_8_9_0 _1_2_3_4_5_6_7_8_9_0_1_2_3_4"
    A31r$="50450145950595050595 0595055579555050504521455050" 'sharp
    A32r$="50450145653565353565 3565355599555050504501455050" '-3 15 -21 L=24
    A33r$="50452145950595050595 0595055599555050504501455050" : END SELECT
    Apm$="5051525045465046515550 47504751535057" : Dpm=1
     V=FNR1(0,1006.4) : V=FNR1(0,2006.4) : V=FNR1(30,-9)
   CASE -7 :   Arr$=FNRE$((FNTIM(9,T)+FNTIM(13,T))/2,3)
 
предпоследняя строка сценария, это и есть указания ревербератору.
Первые два обращения устанавливают точки заброса эха (с долей, указанной в дробной части), а третье устанавливает 30% в качестве доли звука, считанного из ревербератора и вновь запущенного в него обратно наравне с только что пришедшим звуком. 

   Рабочее обращение к ревербератору выглядит так - A=A+FNR1(A,-1)
Ревербератор считывает из текущей точки массива эхо, и амплитуда эха добавляется к амплитуде звука.
   Кроме того, получив амплитуду пришедшего звука, и считав эхо, ревербератор совершает следующие действия:
- продвигает текущую точку на единицу вперёд, навстречу эху
- берёт 30% амплитуды считанного эха и складывает с амплитудой пришедшего звука.
- 0.4 результата прибавляет к амплитуде по относительному адресу 1006
- 0.4 того же результата прибавляет к амплитуде по относительному адресу 2006

  Таким образом, текущая точка считывания эха ползёт по массиву ревербератора, а амплитуда звука для эха постоянно забрасывается наперёд, чтобы считать её в будущем.
  Быстро ли работает ревербератор? Не слишком ли обращение к нему задерживает время счёта?
  Поговорим о скорости озвучивания.


   БЫСТРОДЕЙСТВИЕ ЭЛЕМЕНТОВ ПРОГРАММЫ ТРИО

   Хотя Турбо Бейсик является языком высокого уровня, код, создаваемый им при компиляции, работает достаточно быстро - всего лишь в 1.5 - 3 раза медленнее того чего можно было бы достичь, программируя в машинных кодах. Многое зависит от быстродействия компьютера, а точнее, от быстродействия шины, поскольку Бейсик при каждом своём действии лезет в память.
   И если быстродействие шины обычно составляет от 66 до 200 Мгц, то частота, с которой Бейсик способен выполнять операцию присвоения типа А=В на том ноутбуке, на котором я в данный момент работаю, составляет 7 МГц. А поскольку вся программа состоит из столь же простых операторов, то  и общая скорость озвучивания будет соответствующая.
А какая она будет? Давайте измерим время звучания записи, и сравним это время со временем, необходимым для создания этой записи программой ТРИО.

Запись небольшого фрагмента мелодии звуками аккордеона, звучит 14 сек.
Озвучивание этого фрагмента по приведённому выше сценарию без эха продолжалось 16 сек,
а с подключением ревербератора для создания эха - 19 сек.
  Таким образом, заброс эха в 2 точки увеличивает время озвучивания на (19-16)/16=19%.
  Вместе с тем, поскольку время озвучивания не сильно превышает времени звучания записи, быстродействие программы можно считать приемлемым.
  Более сложный звук - колокол с тремя обертонами записывается дольше - 24 сек без эха и 29 сек с эхом. Очень простой звук, синусоида - 13 сек.

  Массив ревербератора обычно очищается в начале каждого нового звука, но делается это очень быстро - всего лишь .0024 сек требуется для этого. 

  Разумеется, если мы привлечём к работе всех трёх МУЗов, то время озвучивания возрастёт в 3 раза. А если один из МУЗов будет играть аккордами, то время ещё возрастёт, но не так сильно.


   ВКЛЮЧЕНИЕ И ВЫКЛЮЧЕНИЕ ЭХА

  Управлять эхом можно внутри сценария - V=FNR1(0,-11) и ревербератор по входу 1 включён.
V=FNR1(0,-10) - и ревербератор по входу 1 выключен.
  Но неплохо было бы управлять ревербератором из партитуры.
  Давайте, посмотрим на партитуру того самого отрывка длительностью 14 сек, о котором говорилось выше:

 1 ================= TFfil.TXT   VEL= 23000
  R=7 H=3 exo=0 M=1
F= 311.1300048828125  T1= 13524  T2= 276
F= 349.2300109863281  T1= 13524  T2= 276
F= 392  T1= 27048  T2= 552
F= 349.2300109863281  T1= 13524  T2= 276
F= 392  T1= 13524  T2= 276
F= 349.2300109863281  T1= 27048  T2= 552
F= 311.1300048828125  T1= 13524  T2= 276
F= 293.6600036621094  T1= 13524  T2= 276
F= 311.1300048828125  T1= 58604  T2= 1196
 L= 13800
F= 293.6600036621094  T1= 13524  T2= 276
F= 311.1300048828125  T1= 13524  T2= 276
F= 261.6300048828125  T1= 27048  T2= 552
F= 293.6600036621094  T1= 13524  T2= 276
F= 311.1300048828125  T1= 13524  T2= 276
F= 349.2300109863281  T1= 27048  T2= 552
F= 392  T1= 13524  T2= 276
F= 415.2999877929688  T1= 13524  T2= 276
F= 466.1600036621094  T1= 27048  T2= 552
F= 392  T1= 27048  T2= 552
 L= 13800
F= 415.2999877929688  T1= 13524  T2= 276
F= 466.1600036621094  T1= 13524  T2= 276
 2 ============
,,,

что там написано во второй строке? Какие там указания?
  R=7 - сценарий звука аккордеона, этот сценарий мы выше видели
  H=3 - звук средней громкости
  exo=0 - этого мы могли бы и не писать, эхо по умолчанию отсутствует
  M=1 - тоже можно не писать - коэффициент, на который умножается частота, равен 1, если не указано иначе.

  Запустим программу ТРИО с партитурой TFfil.TXT на исполнение. Получим звуки аккордеона без эха.
  Тут нужно посмотреть на верхнюю осциллограмму рисунка, ту, где эхо=0.
  На осциллограмме видно окончание одного звука и начало следующего. Звук не кончается резко, на протяжении 20-ти семплов амплитуда его плавно сводится к нулю. Это сделано для того, чтобы не слышались хлопки в момент окончания звука.
  Затем идёт пауза длительностью 276 сэмплов (T2= 276) и очень плавное нарастание следующего звука.

  Следующая осциллограмма получается, если в сценарии указать ехо=1
  На ней появились пички эха там, где генерируется звук, но там, где звук обрывается, обрывается и эхо. Пауза после звука чиста.

  На записи с указанием ехо=2 эхо выходит в паузу и заполняет её. Но в момент появления нового звука ревербератор очищается. Новый звук начинается в тишине.

  Указание ехо=3 оставляет в ревербераторе остатки прежнего эха, и эхо плавно перетекает со старого звука на новый. В момент появления нового звука обнулением R(0)=0 ликвидируются точки заброса старого звука, но старое эхо в ревербераторе продолжает жить, постепенно затухая.
А новый звук, может быть, установит другие точки заброса эха.

  Так всё и работает. На нижнем слайде - общая картина звуков партитуры TFfil, развивающихся  по сценарию 7 с ехо=3. Амплитуды звуков с эхом различаются, в зависимости от частоты ноты. Связано это с тем, что заброс мы делаем в одни и те же точки, не ориентируясь на частоту. Вот если бы мы первым параметром в обращении к функции FNR1 указали не ноль а частоту - V=FNR1(F,1006.4), то тогда бы точки заброса были бы координированы с частотой, и мы получили бы очень схожие результаты интерференции основного звука со звуком эха.

  Все переключения режимов эха и добавление эха в паузах осуществляется МУЗом. Глобальные обозначения, связанные с эхом, имеют индексы "n" для MUZ1 и "m" для MUZ1, и не имеют индекса для MUZ3. Например, строки для дублицирования используются такие -
REVn$, REVm$ и REV$, а обращения к ревербератору такие - FNRn1, FNRm1 и FNR1.

 ==========
Запись фрагмента партитуры звуками аккордеона без эха и с ехо=3, и следом - то же со звуками фортепьяно (октавой повыше, с М=2) можно прослушать тут –
https://yadi.sk/d/wfxX19yasfYf7
 ======================================================== 17.06.2016

 ПРИЛОЖЕНИЕ. НАЧАЛО ПРОГРАММЫ и ТЕКСТ третьего МУЗа

   Под строками МУЗа, обрабатывающими эхо, сделаны просветы. В начале программы, помимо Дирижёра - CASE z, имеется и ветка CASE w, используемая
для звуковых проб.

'============= TRIO.BAS
10 INPUT A$
   SELECT CASE MID$(A$,1,1)
    CASE "e"
      STOP
    CASE "o"
      A1$=A$ : IF LEN(A1$)=2 THEN A1$=MID$(A1$,2)+".wav"
      OPEN "B",#1,A1$ : GOTO 10
    CASE "c"
      CLOSE #1 : GOTO 10
    CASE "l"
      PRINT LOF(1),LOC(1) : GOTO 10
    CASE "s"
      SEEK #1,VAL(MID$(A$,2)) : GOTO 10
    CASE "p"
      PUT$ #1,MID$(A$,2) : GOTO 10
    CASE "g"
      GET$ #1,VAL(MID$(A$,2)),S$
      PRINT S$,"loc=";LOC(1) : GOTO 10
    CASE "h" 'put the head of wav file
      GOSUB 1000 : GOTO 10
    CASE "w" 'make wav sound
SEEK #1,44
 hhh=1 : VEL=32000 : A=FNSS3(0,0) : FF=1 : FF2=1 : II=2 : K=9
  K=FNRn1(0,0) : K=FNRm1(0,0) : K=FNR1(0,0)
 FOR I=1 TO 2000  : M%=0 : PUT$ #1,MKI$(M%) : NEXT I
 FOR I=1 TO 20000  : M%=INT(4000*FNSS3(FF*260.74*1.5,K)) : PUT$ #1,MKI$(M%) : NEXT I
 FOR I=1 TO 500  : M%=0 : PUT$ #1,MKI$(M%) : NEXT I
 FOR I=1 TO 20000*II : M%=INT(4000*FNSS3(FF*FF2*260.75,K)) : PUT$ #1,MKI$(M%) : NEXT I
 FOR I=1 TO 1000  : M%=0 : PUT$ #1,MKI$(M%) : NEXT I
 FOR I=1 TO 20000  : M%=INT(4000*FNSS3(FF*260.73,K)) : PUT$ #1,MKI$(M%) : NEXT I
 FOR I=1 TO 500  : M%=0 : PUT$ #1,MKI$(M%) : NEXT I
 FOR I=1 TO 30000*II  : M%=INT(4000*FNSS3(FF*FF2*260.74/1.5,K)) : PUT$ #1,MKI$(M%) : NEXT I
 FOR I=1 TO 30000  : M%=0 : PUT$ #1,MKI$(M%) : NEXT I
GOTO 10

    CASE "z" 'make wav record - oZvuchivanie
 SEEK #1,44 : VEL=32000 : FEF=0 : REF=0 : COF=1
  K=FNRn1(0,0) : K=FNRm1(0,0) : K=FNR1(0,0)
  CALL MUZ1(-1) : CALL MUZ2(-1) : CALL MUZ3(-1)
 'OPEN "TF1.TXT" FOR INPUT AS #11 : CALL MUZ1(1)
 'OPEN "TF2.TXT" FOR INPUT AS #12 : CALL MUZ2(1)
 OPEN "TFfil.TXT" FOR INPUT AS #13 : CALL MUZ3(1)

12 S$=INKEY$ : IF S$=" " THEN GOTO 10
  FEF=0 : REF=0 : PRECOF=0
  CALL MUZ1(0) : CALL MUZ2(0) : CALL MUZ3(0) 'go on please
  COF=PRECOF : IF COF=1 THEN M%=INT(FEF*1000) : PUT$ #1,MKI$(M%)
  IF REF=1 THEN 12
  GOSUB 1000 : CLOSE #1 : PRINT "Ok" : STOP

END SELECT : GOTO 10

'===========

 SUB MUZ3(K)
STATIC L$,Re,Co,F,R,T,T1,T2,TB,TE,H,KK,M,E
SHARED FEF,REF,COF,PRECOF,ARE3,R() '====
   KK=K
  IF KK=-1 THEN Re=0 : Co=0 : EXIT SUB
  IF KK>0 THEN
     Re=1 : Co=1 : H=1 : M=1 : T1=0 : T2=0
     TB=1 : TE=20 : R=KK : E=0 : EXIT SUB
  END IF
  IF Re=0 THEN EXIT SUB
  IF Co=0 AND COF=1 THEN REF=1 : EXIT SUB ELSE Co=1
MU3:
  IF T1=0 AND T2=0 THEN
   LINE INPUT #13,L$
   IF MID$(L$,6,3)="===" THEN PRINT "3 "+L$ : Co=0 : REF=1 : EXIT SUB
   IF LEFT$(L$,3)=",,," THEN CLOSE #13 : Re=0 : EXIT SUB
   I=INSTR(L$,"H") : IF I>0 THEN H=VAL(MID$(L$,I+2))
   I=INSTR(L$,"exo=") : IF I>0 THEN I=ASC(MID$(L$,I+4,1))-48 : IF I>=0 AND I<4 THEN E=I

   I=INSTR(L$,"R=") : IF I>0 THEN R=VAL(MID$(L$,I+2))
   I=INSTR(L$,"M=") : IF I>0 THEN M=VAL(MID$(L$,I+2))
   I=INSTR(L$,"G=") : IF I>0 THEN I=FNAcc(MID$(L$,I),3)
   I=INSTR(L$,"A") : IF I>0 THEN ARE3=FNArr(MID$(L$,I),3)
   I=INSTR(L$,"U") : IF I>0 THEN I=FNUdd(MID$(L$,I),3)
   I=INSTR(L$,"TB") : IF I>0 THEN TB=VAL(MID$(L$,I+3)) : IF TB<1 THEN TB=1
   I=INSTR(L$,"TE") : IF I>0 THEN TE=VAL(MID$(L$,I+3)) : IF TE<1 THEN TE=1
   I=INSTR(L$,"L") : IF I>0 THEN T2=VAL(MID$(L$,I+2)) : F=0 : T1=0
   I=INSTR(L$,"F") : IF I>0 THEN
     SELECT CASE E : CASE 0 : A=FNR1(0,-10)
        CASE 3 : R(0)=0 : A=FNR1(0,-11) : CASE 1,2 : A=FNR1(0,0) : END SELECT

     F=VAL(MID$(L$,I+3)) : T=TB : AO=FNSS3(0,0) : print F
     I=INSTR(L$,"T1") : IF I>0 THEN T1=VAL(MID$(L$,I+3))
     I=INSTR(L$,"T2") : IF I>0 THEN T2=VAL(MID$(L$,I+3))
        END IF : GOTO MU3
  END IF
    PRECOF=1 : REF=1
    IF F=0 THEN  'pause
      IF E>1 THEN FEF=FEF+FNR1(0,-1)*H
      T2=T2-1 : EXIT SUB : END IF

    AO=FNSS3(F*M,R)*H : T1=T1-1: IF T1<TE THEN AO=AO*T1/TE
    IF T>1 THEN T=T-1 : AO=AO*(1-T/TB)
    IF T1<=0 THEN F=0
    FEF=FEF+AO
 END SUB
'==================================================


Рецензии