Прежде всего, вспомним, как мы работали со звуковыми данными, как помещали их в файл.
При остановке записи сначала записывается заголовок (WaveHeader сам его пишет в файл), а потом открывается этот самый файл, указатель устанавливается в конец файла и пишутся звуковые данные.
Изменения звука нужно делать перед записью звуковых данных в файл. Делаются они непосредственно с байтами. Наш звук 16-разрядный, значит, одна единица звуковых данных в файле - 2 байта (16 бит). И с этой единицей можно работать.
Здесь всё сосредоточено во вложенной схеме. Сначала указатель звуковых данных в памяти устанавливается на начало. Затем размер данных делится на 2, потому что размер представлен в байтах, а извлекать надо по 2 байта, тогда цикл должен срабатывать в 2 раза меньше раз, чем размер данных.
И каждый раз цикл извлекает по 2 байта (у DataToFile Type=dtWord). Именно с этими байтами нужно что-то делать. А что - это целиком и полностью ваша фантазия. Впрочем, кое-какие примеры стоит показать. Помните только, 2 байта могут иметь 655356 вариантов, то есть число в этих пределах (0 - 65535) будет нам выдаваться.
Здесь реализуется эффект обратного воспроизведения. Точнее, плеер-то воспроизводит правильно, но в файле все байты идут задом наперёд. Посмотрите на схему. При обработке все байты записываются в массив целых чисел, а потом, когда запись закончится (т.е. выдача всех байтов закончится), начинается их обратная выдача (у ArrayEnum Type=Dec). При этом новая последовательность записывается в память, а оттуда - копируется прямиков в файл.
Что ещё можно сделать? Можно много чего сделать, однако нужно много экспериментировать или хотя бы знать, как делаются уже известные всем эффекты (типа эха, хора и т. д.). Экспериментируя со значениями байт звуковых данных, вы найдёте множество интересных и полезных конкретно для вас эффектов. А также помните, что вы всегда сможете извлечь из файла звуковые данные (их размер можно прочитать из заголовка) и вновь применять к ним эффекты.
P.S. Следите за обновлениями блога - скоро появятся новые видеоуроки ко многим предыдущим (и, возможно, текущим) статьям.
Если у вас есть свой сайт, то сервис раскрутки и продвижения сайтов в интернете вам будет обязательно нужен. От рекламы зависит посещаемость.
Сайт компании "Недвижимость и кредит" предлагает квартиры в Воронеже купить. Выгодные цены, хорошие квартиры. Рекомендую.
Перед поездкой в Тайланд, Флоренцию, Малайзию или куда угодно, узнайте отзывы туристов об отдыхе. Сходите на сайт Туристер.ру и поситайте.
Нет ли компонентов для других эффектов?
ОтветитьУдалитьА также: раньше в HiAsm был компонент для наложения эффектов на канал, где же он теперь?
Старый компонент для наложеня эффектов на канал устарел безвозвратно. Он не работает с технологией менеджеров, на которую переведны все компоненты BASS. И создавать новый никто не хочет.
ОтветитьУдалитьДля других эффектов в HiAsm ничего нет. Да там, собственно, и не эффекты, а просто несколько модификаторов звука.
Ну, принцип-то вам известен, суть звуковых данных ясна. Так что можете сами что-то придумать.
На основании ваших проектов сделал программу-вокал ремовер (удаление вокала).
ОтветитьУдалитьMake(delphi)
ver(4.04 build 184)
Add(MainForm,2953706,21,105)
{
Height=100
Caption="Удаление вокала"
BorderStyle=3
Position=1
link(onCreate,15457736:doDelete,[])
}
Add(Label,15805043,21,252)
{
Left=5
Top=10
Width=87
Height=17
Caption="Исходный файл:"
}
Add(Edit,4113927,203,196)
{
Left=95
Top=10
Width=235
Text=""
link(onChange,943440:doGet,[])
}
Add(Button,15323027,21,196)
{
Left=330
Top=10
Caption="Обзор"
link(onClick,3628228:doExecute,[])
}
Add(Button,16027011,21,308)
{
Left=155
Top=40
Width=90
Caption="Удалить вокал"
link(onClick,13660407:doOpen,[])
}
Add(ODialog,3628228,77,196)
{
Filter="WAV|*.wav"
Title=""
FileName=""
link(onExecute,4113927:doText,[])
}
Add(FileStream,13660407,203,315)
{
link(onLoad,15538447:doEvent1,[])
link(FileName,4113927:Text,[])
}
Add(Hub,15538447,259,315)
{
OutCount=3
link(onEvent2,12252318:doCalc,[(291,328)(291,398)])
link(onEvent3,16150303:doWork1,[(282,335)(282,454)])
}
Add(MathParse,12252318,308,392)
{
DataCount=1
MathStr="%1 / 2 - 44"
link(X1,13660407:Size,[(314,370)(216,370)])
}
Add(MultiElement,16150303,312,448)
{
link(onEvent1,463187:doEvent1,[])
link(Data1,12252318:Result,[(318,436)(314,436)])
link(Data2,13660407:Stream,[(325,433)(209,433)])
}
BEGIN_SDK
Add(EditMulti,8730838,21,14)
{
EventCount=1
WorkCount=1
DataCount=2
Width=874
Height=501
link(doWork1,13939583:doEvent1,[(73,20)(73,104)])
}
Add(For,16360143,210,133)
{
Start=1
link(onEvent,8564489:doEvent1,[])
link(onStop,4517232:doFor,[(254,146)(254,384)])
link(End,312401:Var2,[])
}
Add(DataToFile,10041605,336,84)
{
Type=1
Point(doPosition)
link(onGet,12821300:doValue,[(373,90)(373,125)])
link(Stream,305794:Var3,[(342,53)])
}
Add(Hub,13939583,126,98)
{
link(onEvent1,1841652:doData,[])
link(onEvent2,16360143:doFor,[(150,111)(150,139)])
}
Add(DoData,1841652,231,98)
{
Data=Integer(44)
link(onEventData,198992:doEvent1,[])
}
Add(IntegerArray,5715532,518,21)
{
IntArray=[]
}
Add(ArrayRW,13682674,518,105)
{
link(Array,11464727:Var2,[])
link(Value,12821300:Value,[(538,93)(492,93)(492,163)(447,163)])
}
Add(Memory,12821300,441,119)
{
link(onData,13682674:doAdd,[])
}
Add(Hub,8564489,259,133)
{
link(onEvent1,10041605:doGet,[(297,139)(297,101)])
link(onEvent2,11569084:doGet,[(295,146)(295,262)])
}
Add(DataToFile,11569084,315,245)
{
Type=1
Point(doPosition)
link(onGet,3141248:doValue,[(373,251)(373,279)])
link(Stream,305794:Var2,[])
}
Add(Hub,198992,273,98)
{
link(onEvent1,10041605:doPosition,[])
link(onEvent2,11569084:doPosition,[(303,111)(303,269)])
}
Add(IntegerArray,3932738,476,175)
{
IntArray=[]
}
Add(ArrayRW,13305406,476,259)
{
link(Array,13605494:Var2,[])
link(Value,3141248:Value,[(496,247)(450,247)(450,317)(405,317)])
}
Add(Memory,3141248,399,273)
{
link(onData,13305406:doAdd,[])
}
Add(For,4517232,266,378)
{
Start=1
link(onEvent,1765156:doOperation,[])
link(onStop,9980276:doData,[(307,391)(307,336)(667,336)(667,258)])
link(End,312401:Var3,[(279,124)])
}
Add(GetDataEx,312401,217,119)
{
link(Data,8730838:Data1,[(223,77)(29,77)])
}
Add(Hub,10556347,364,378)
{
link(onEvent1,1133828:doRead,[])
link(onEvent2,3580966:doRead,[(452,391)(452,447)])
}
Add(Math,1765156,315,378)
{
OpType=1
Op2=1
link(onResult,10556347:doEvent1,[])
}
Add(ArrayRW,1133828,574,378)
{
link(onRead,1516077:doEvent1,[])
link(Array,11464727:Var3,[(580,82)])
}
Add(GetDataEx,11464727,518,77)
{
link(Data,5715532:Array,[])
}
Add(MultiElementEx,732040,630,441)
ОтветитьУдалить{
@Hint=#21:Число противоположное|
link(onInvert,1516077:doEvent2,[(670,447)(670,391)])
link(1,3580966:Item,[(636,427)(561,427)(561,485)(531,485)])
}
BEGIN_SDK
Add(EditMultiEx,12104346,21,21)
{
WorkCount=#88:doInvert=Выдает в поток onInvert число, противоположное числу, переданному в этом потоке|
EventCount=#8:onInvert|
DataCount=#1:1|
Width=258
Height=368
link(doInvert,14568360:doEvent1,[(35,27)(35,34)])
}
Add(StrMask,14821382,84,84)
{
Mask="-*"
link(onFalse,8339546:doOperation,[])
link(onTrue,12092067:doTrim,[(135,97)(135,146)])
}
Add(Memory,3572919,147,28)
{
}
Add(Hub,14568360,49,28)
{
link(onEvent1,3572919:doValue,[])
link(onEvent2,14821382:doCompare,[(73,41)(73,90)])
}
Add(Math,8339546,140,84)
{
OpType=1
Op1=327678
link(onResult,10554907:doWork2,[(226,90)(226,27)])
link(Op2,5466643:Var2,[])
}
Add(Trim,12092067,154,140)
{
Char="-"
link(onTrim,5966681:doOperation,[])
link(Text,5466643:Var3,[(160,68)])
}
Add(GetDataEx,5466643,147,63)
{
link(Data,3572919:Value,[])
}
Add(Math,5966681,210,140)
{
Op2=327678
link(onResult,10554907:doWork3,[(263,146)])
}
Add(HubEx,10554907,259,21)
{
link(onEvent,12104346:onInvert,[])
}
END_SDK
Add(ArrayRW,3580966,525,441)
{
link(onRead,15657302:doOperation,[])
link(Array,13605494:Var3,[(531,229)])
}
Add(GetDataEx,13605494,476,224)
{
link(Data,3932738:Array,[])
}
Add(Math,15657302,574,441)
{
OpType=1
Op2=327678
link(onResult,732040:doInvert,[])
}
Add(DoData,9980276,700,252)
{
link(onEventData,7927977:doEvent1,[])
link(Data,1457110:Var2,[])
}
Add(GetDataEx,305794,315,48)
{
Angle=3
link(Data,8730838:Data2,[(36,53)])
}
Add(Hub,7927977,756,252)
{
link(onEvent1,8730838:onEvent1,[(814,258)(814,20)])
}
Add(Hub,1516077,679,378)
{
InCount=2
OutCount=1
link(onEvent1,13879526:doPut,[])
}
Add(MemoryStream,9669894,700,196)
{
}
Add(DataToFile,13879526,707,378)
{
Type=1
link(Stream,1457110:Var3,[(713,243)])
}
Add(GetDataEx,1457110,700,238)
{
link(Data,9669894:Stream,[])
}
END_SDK
Add(WaveHeader,943440,406,189)
{
Point(doGet)
Point(onGet)
Point(varFrequency)
Point(varChannels)
Point(varSize)
}
Add(Hub,463187,364,448)
{
OutCount=6
link(onEvent1,11574171:doOperation,[(385,454)(385,370)])
link(onEvent2,11657445:doCreate,[(388,461)(388,419)])
link(onEvent3,16512479:doData,[])
link(onEvent4,8979798:doCopyFromStream,[(476,475)(476,440)])
link(onEvent5,8979798:doClose,[(476,482)(476,426)])
link(onEvent6,11388380:doExecute,[(441,489)(441,517)])
}
Add(WaveHeader,11657445,399,413)
{
FileName="temp\\tempfile.wav"
Frequency=0
link(onCreate,8979798:doOpen,[])
link(Frequency,11574171:Result,[])
link(Size,943440:varSize,[])
}
Add(FileStream,8979798,574,413)
{
FileName="temp\\tempfile.wav"
Mode=2
Point(doPosition)
Point(doCopyFromStream)
}
Add(DoData,16512479,448,462)
{
link(onEventData,8979798:doPosition,[(527,468)(527,433)])
link(Data,8979798:Size,[(454,454)(587,454)])
}
Add(FileTools,15457736,77,105)
{
DelToRecycle=1
link(FileName,15975816:Value,[])
}
Add(Memory,15975816,77,56)
{
Default=String(temp\\tempfile.wav)
}
Add(Math,11574171,406,364)
{
OpType=2
Op2=2
link(Op1,943440:varFrequency,[])
}
Add(SDialog,11388380,511,511)
{
Filter="Wav|*.wav"
Title=""
FileName=""
link(onExecute,1831159:doMove,[])
}
Add(FileTools,1831159,560,511)
{
link(FileName,10080160:Value,[])
}
Add(Memory,10080160,560,462)
{
Default=String(temp\\tempfile.wav)
}
Но есть недоделки:
1. пробовал на частоте дискретизации 44100 гц. При использовании другой скорость была замедленной.
2. пробовал на коротких кусках песни. при попытке удалить вокал из целой песни сказал Out of memory
Помогите, как доделать?