Форум: "Media";
Текущий архив: 2006.12.17;
Скачать: [xml.tar.bz2];
ВнизWAV - TimeStreatch (сжатие звука по времени) ... Найти похожие ветки
← →
Wm.DIGGER © (2006-05-03 12:53) [0]Господа, подскажите пожалуйста. Мне нужно реализовать алгоритм TimeStreatch - сжатие звука по времени ... т.е. допустим время звучания wav-файла 3 сек. мне нужно сделать чтобы оно было 2,5 сек. Эта функция есть почти во всех звуковых редакторах и в каждом используется свой алгоритм, но вот описания хотябы одного алгоритма я нигде не нашёл ...
Пошёл самым простым путём: решил рассчитать коэффициент (шаг) и просто выбросить семплы в соответствие с этим шагом ... т.е. скажем из 3 сек. сделать 2,5 при частоте 48000Гц 16 bit Mono ... после расчётов получил шаг = 4 ... т.е. отбрасываю каждый 4-тый семпл последовательности ...
ок - получаю новый wav-файл продолжительностью 2,5 сек ...
но вот голос (в файле был записан голос) :)))) голос становится "писклявым" :) т.е. искажается ...
я понимаю, что сделанное мной мягко говоря "тупо" :)
подскажите, как выполнить сжатие по времени и получить звук без искажений ... ?
← →
Jeer © (2006-05-03 13:05) [1]Resampling.
Если в лоб, то делается интерполяция (линейная или более высоких порядков - обычно куба достаточно) между отсчетами исходного звука и выбирается ближайшая точка к узлу новой временной сетки.
← →
Jeer © (2006-05-03 13:06) [2]А сжатие временной оси естественно приведет к повышению тона.
← →
Wm.DIGGER © (2006-05-03 13:24) [3]но Resampling это другая фанкция совсем ...
это пересчёт семплов из 48000 в 44100 скажем и т.п. ...
(может ошибаюсь, но вроде нет ...)
а пример можно в виде кода ...
вот скажем у нас просто массив: m:array[0..1023] of SmallInt;
в нём записано 1024 семпла (для 16 бит 1 сэмпл - 2 байта - SmallInt).
как сдалать то, что ты написал выше? :)
← →
Jeer © (2006-05-03 14:05) [4]Тогда непонятно, что хочешь ты.
Как ты себе представляешь - вся пестня звучит 1 час, ты хочешь чтобы звучала 30 мин. Скорость проигрывания должна увеличиться в два раза и
> Jeer © (03.05.06 13:06) [2]
Если тебе надо, чтобы длительность была меньше без частотных искажений, то просто отрезаешь "лишний" участок.
← →
ancara © (2006-05-03 16:38) [5]А я, кажись, понял что он хочет. Ему нужно чтоб время сократилось а тональность сохранилась. В каком-то проигрывателе, вроде PowerDVD, (да и вообще во многих) можно регулировать скорость воспроизведения, можно установить, например, 2-х кратную. В этом случае, персонажи фильма реально начинают тараторить, т.е. говорить своими голосами, но быстрее.
Как реализовано там не знаю, но мне кажется вырезаются не отдельные сэмплы а их последовательности, т.е. куски аудиотрека такие... Может по 100 мс или меньше, надо экспериментально подбирать, ИМХО.
← →
Wm.DIGGER © (2006-05-03 23:09) [6]господа, TimeStretch ... есть в любом звуковом редакторе! ...
не нужно пытаться ответить на вопрос, если не знаете о чём речь ...
из часа 30 мин сделать никто не пытается ... как правило коррекция проводиться не более чем на 10% иначе даже самые передовые алгоритмы начинаю давать артефакты ...
ancara да, именно "ускорение или замедление" звука без потери тональности ... меня интерисует замедление ...
там весь звук разбивается на участки определённой длинны ...
и проводится какой-то анализ ... после чего выводиться зависимоть ...
но вот что это за анализ и какая должна быть зависимость я и не знаю ...
мне посоветовали читать про ряды Фурье ...
но читать можно вечно ...
здесь бы алгоритм, а лучше его реализацию ...
← →
Wm.DIGGER © (2006-05-04 02:01) [7]вот код кидаю ... что у меня получается ...
звук сжимается по времени (идёт быстрее), но становиться высоким (если это голос, то писклявым ...) а в звуковых редакторах тоже сжимается, но остаётся нормальным по высоте звучания ...
чего делать?
uses MMSystem;
type
hWAVEHeader = record
idRiff:array[0..3] of Char;
RiffLen:LongInt;
idWave:array[0..3] of Char;
idFmt:array[0..3] of Char;
InfoLen:LongInt;
WaveType:SmallInt;
Channels:SmallInt;
Freq:LongInt;
BytesPerSec:LongInt;
Align:SmallInt;
Bits:SmallInt;
end;
hWAVEDATAHeader = record
idData:array[0..3] of Char;
DataLen:LongInt;
end;
procedure WAVETimeStretch(WAVEFileName:string; NewTime:Real);
var WF,SWF:TFileStream;
WAVEHeader:hWAVEHeader;
DATAHeader:hWAVEDATAHeader;
NBuf,SBuf:array[0..1023] of SmallInt;
BufSize,BStep,NTStep,SStep,SCount:Word;
NewDataLength:integer;
CurrentTime:Real;
begin
WF := TFileStream.Create(WAVEFileName,fmOpenReadWrite);
WF.Position := 0;
WF.ReadBuffer(WAVEHeader,SizeOF(WAVEHeader));
WF.ReadBuffer(DATAHeader,SizeOF(DATAHeader));
SWF := TFileStream.Create(WAVEFileName + ".new.wav",fmCreate);
SWF.WriteBuffer(WAVEHeader,SizeOF(WAVEHeader));
SWF.WriteBuffer(DATAHeader,SizeOF(DATAHeader));
NewDataLength := Round(NewTime * WAVEHeader.Align * WAVEHeader.Freq);
CurrentTime := (NewDataLength / WAVEHeader.Align) / WAVEHeader.Freq; //length in seconds
NTStep := Round((DATAHeader.DataLen / WAVEHeader.Align) / (DATAHeader.DataLen / WAVEHeader.Align - NewDataLength / WAVEHeader.Align));
while WF.Position < DATAHeader.DataLen do
begin
if (WF.Position + SizeOF(NBuf)) < DATAHeader.DataLen then BufSize := SizeOF(NBuf)
else BufSize := DATAHeader.DataLen - WF.Position;
WF.Read(NBuf,BufSize);
BStep := 0; SStep := 0; SCount := 1;
while BStep < 1024 do
begin
if SCount < NTStep then begin SBuf[SStep] := NBuf[BStep]; inc(SStep); inc(SCount); end
else SCount := 1;
inc(BStep);
end;
dec(SStep);
SWF.Write(SBuf,SStep * SizeOF(SmallInt));
end;
SWF.Position := 0;
WAVEHeader := SetWAVEHeader(WAVEHeader.Channels,WAVEHeader.Freq,WAVEHeader.Bits,CurrentTime);
DATAHeader := SetWAVEDATAHeader(WAVEHeader);
SWF.WriteBuffer(WAVEHeader,SizeOF(WAVEHeader));
SWF.WriteBuffer(DATAHeader,SizeOF(DATAHeader));
SWF.Free;
WF.Free;
end;
← →
ancara © (2006-05-04 10:31) [8]ну так попробуй вырезать кусками по 50 - 100 мс, что получится?
← →
Jeer © (2006-05-04 11:12) [9]Wm.DIGGER © (03.05.06 23:09) [6]
Надо точнее задавать вопросы и обрисовывать задачу, тогда яснее на что отвечать.
Если не оговорен тип звука, то обсуждение данного эффекта бессмысленно.
Очевидно, что композитный звук из чистых тонов сжать по времени без изменения тональности не удастся.
Cool Edit не меняет тональность в этом случае только для TimeStretch типа "Fast Talker", а для остальных типов - заметное изменение тона, что и понятно.
Все остальные типы композитного звука с широким спектром могут быть обработаны данным эффектом путем отделения нижних (фонемных) и верхних
(тебральных) частот.
Делать это, действительно, лучше с использованием FFT.
Алгоритм такой:
Применяется прямое FFT - получаем спектр фонограммы.
На уровне разделения 50-80 Гц выделяются нижний и верхний спектры фонограммы с небольшим наложением друг на друга.
Нижняя часть спектра транспонируется (растягивается) вверх по частоте в 1.0 - 2.0 раз (больше обычно не делается).
Спектры складываются и применяется обратное FFT для восстановления сигнала.
Вуаля.
← →
Wm.DIGGER © (2006-05-04 14:47) [10]Jeer это хорошо ... но ты можешь привести пример реализации БПФ ... ? т.е. не самого БПФ, а как это использовать на практике для звука ... как выбрать размер окна хотябы? напиши, я думаю не только мне будет интересно ...
P.S. про тип звука я говорил, это речь - чистый голос ...
← →
Wm.DIGGER © (2006-05-04 15:24) [11]собственно могу даже упростить задачу ...
я дам процедуру БПФ (FFT) ... можешь написать, как её применить конкретно к звуку ... ? ну очень нужно ... плиззз!
type TDArray = array of Double;
procedure FastFourierTransform(var a : TDArray;
nn : Integer;
InverseFFT : Boolean);
var
ii : Integer;
jj : Integer;
n : Integer;
mmax : Integer;
m : Integer;
j : Integer;
istep : Integer;
i : Integer;
isign : Integer;
wtemp : Double;
wr : Double;
wpr : Double;
wpi : Double;
wi : Double;
theta : Double;
tempr : Double;
tempi : Double;
begin
if InverseFFT then
begin
isign := -1;
end
else
begin
isign := 1;
end;
n := 2*nn;
j := 1;
ii:=1;
while ii<=nn do
begin
i := 2*ii-1;
if j>i then
begin
tempr := a[j-1];
tempi := a[j];
a[j-1] := a[i-1];
a[j] := a[i];
a[i-1] := tempr;
a[i] := tempi;
end;
m := n div 2;
while (m>=2) and (j>m) do
begin
j := j-m;
m := m div 2;
end;
j := j+m;
Inc(ii);
end;
mmax := 2;
while n>mmax do
begin
istep := 2*mmax;
theta := 2*Pi/(isign*mmax);
wpr := -2.0*sqr(sin(0.5*theta));
wpi := sin(theta);
wr := 1.0;
wi := 0.0;
ii:=1;
while ii<=mmax div 2 do
begin
m := 2*ii-1;
jj:=0;
while jj<=(n-m) div istep do
begin
i := m+jj*istep;
j := i+mmax;
tempr := wr*a[j-1]-wi*a[j];
tempi := wr*a[j]+wi*a[j-1];
a[j-1] := a[i-1]-tempr;
a[j] := a[i]-tempi;
a[i-1] := a[i-1]+tempr;
a[i] := a[i]+tempi;
Inc(jj);
end;
wtemp := wr;
wr := wr*wpr-wi*wpi+wr;
wi := wi*wpr+wtemp*wpi+wi;
Inc(ii);
end;
mmax := istep;
end;
if InverseFFT then
begin
I:=1;
while I<=2*nn do
begin
a[I-1] := a[I-1]/nn;
Inc(I);
end;
end;
end;
← →
Wm.DIGGER © (2006-05-04 15:32) [12]В зависимости от переданных параметров, может выполняться
как прямое, так и обратное преобразование.
Входные параметры:
nn - Число значений функции. Должно быть степенью
двойки. Алгоритм не проверяет правильность
переданного значения.
a - array [0 .. 2*nn-1] of Real
Значения функции. I-ому значению соответствуют
элементы a[2*I] (вещественная часть)
и a[2*I+1] (мнимая часть).
InverseFFT
- направление преобразования.
True, если обратное, False, если прямое.
Выходные параметры:
a - результат преобразования.
← →
Jeer © (2006-05-04 17:36) [13]Завтра отвечу, но если ты сумеешь сделать новый MPEX - Штейнберг (Steinberg) возмет тебя на работу не глядя.
← →
programania © (2006-05-04 20:15) [14]>ancara © (04.05.06 10:31) [8]
>ну так попробуй вырезать кусками по 50 - 100 мс, что получится?
Получится много треска из-за сильных мгновенных перепадов амплитуды
Вырезать лучше в месте перехода через 0
а еще лучше искать минимальные участки
с самой одинаковой амплитудой и производной
т.е. наклоном на краях равномерно по всему звуку
и их вырезать или вставлять
тогда наверно будет незаметно
>Wm.DIGGER © (04.05.06 15:24) [11]
>я дам процедуру БПФ (FFT) ... можешь написать, как её применить конкретно к звуку ...
Преобразовать в массив частот
Сдвинуть их вниз на 10% от размера массива т.к. он равен размеру массива по времени
Преобразовать назад
Сжать амплитуды по времени на 10% как в [7]
← →
Wm.DIGGER © (2006-05-05 04:16) [15]ну, господа, ну программулю можно?
ну, вот - Преобразовать в массив частот ... а что сразу весь звуковой файл?
нет, а сколько лучше взять ... я же говорил ... там размер окна нужно. какой размер лучше брать? не поленитесь, код напишите ...
← →
Jeer © (2006-05-05 10:57) [16]Wm.DIGGER © (05.05.06 04:16) [15]
> не поленитесь, код напишите ...
Учись аспирант.
Интересно какую математику и информатику ты преподаешь ?
programania © (04.05.06 20:15) [14]
> Преобразовать в массив частот
> Сдвинуть их вниз на 10% от размера массива т.к. он равен
> размеру массива по времени
> Преобразовать назад
Это не то, это - pitch
← →
Wm.DIGGER © (2006-05-05 11:07) [17]а вы, уважаемый, хоть знаете что такое Информатика ... :)))) ?
причём здесь написание кода - это программирование к информатике как науке отношение имеет косвенное ...
а если не знаете, так и скажите ... а то умников я смотрю развилось ...
языком часать все гаразды, а что-то конкретное недождёшся ...
← →
Wm.DIGGER © (2006-05-05 11:34) [18]to programania
вот попытался так ... получилась вообще жопа ... собственно и треск и голос высокий :)
type pDub = array[0..1023] of Double;
procedure FFTS(var FFTWindow:pDub; FFTWindowSize, DMSize:LongInt);
var
dx,
dxx,
Rex, //действ. часть частотного спектра
Imx:pDub //мнимая часть частотного спектра
risize:integer;
i,j:longint;
begin
RISize := FFTWindowSize div 2;
for i := 0 to FFTWindowSize - 1 do dx[i] := FFTWindow[i];
for i := 0 to RISize do begin Rex[i] := 0; Imx[i] := 0; end;
// фурье прямое
for j := 0 to RISize do
for i := 0 to FFTWindowSize - 1 do
begin
Rex[j] := Rex[j] + dx[i] * cos(2*pi*j*i/FFTWindowSize);
Imx[j] := Rex[j] - dx[i] * sin(2*pi*j*i/FFTWindowSize);
end;
// пересчёт амплитуд под новый размер массива
for j := 0 to RISize do
begin
Rex[j] := Rex[j] / (DMSize / 2);
Imx[j] := -Imx[j] / (DMSize / 2);
end;
Rex[0] := Rex[0] / 2;
Rex[RISize] := Rex[RISize] / 2;
//чистим аккумулятор
for i := 0 to FFTWindowSize - 1 do dxx[i] := 0;
//фурье обратное
for j := 0 to RISize do
for i := 0 to DMSize - 1 do
begin
dxx[i] := dxx[i] + Rex[j] * cos(2*pi*j*i/DMSize);
dxx[i] := dxx[i] + Imx[j] * sin(2*pi*j*i/DMSize);
end;
for i := 0 to DMSize - 1 do FFTWindow[i] := trunc(dxx[i]);
end;
← →
Jeer © (2006-05-05 12:16) [19]Wm.DIGGER © (05.05.06 11:07) [17]
А с таким гонором, как у тебя, "аспирант", ты вообще ничего не дождешься.
За тебя делать никто не будет, разве, что деньги получать.
А так - выложи 300 баксов, будет рабочий код time stretch.
Не MPEX, но работать будет.
А иначе - мимо проходи.
Или начни моск искать.
← →
Jeer © (2006-05-05 12:18) [20]
> собственно могу даже упростить задачу ...
> я дам процедуру БПФ (FFT) ...
Вот "осчастливил", надо же.
← →
Wm.DIGGER © (2006-05-05 12:20) [21]Удалено модератором
← →
Jeer © (2006-05-05 12:28) [22]Wm.DIGGER © (05.05.06 12:20) [21]
Как Вы меня назовете - мне безразлично.
Вы не хотите учится, а занимаетесь бестолковым набросом кода и прослушиванием "чего вышло" из динамиков.
Мосг Вам в помощь, но в его неналичии, так же как и применимости определения "дурак" к Вам - я не сомневаюсь.
Будете хамить дальше - найдем и поправим ситуацию.
← →
Wm.DIGGER © (2006-05-05 12:43) [23]Удалено модератором
← →
Jeer © (2006-05-05 13:03) [24]Wm.DIGGER © (05.05.06 12:43) [23]
Давай дальше - ты много знаешь определений, будет на чем учиться, таким как ты.
> не простой набросок кода, а результат проб .
бестолковых проб, заметим.
DSP - это целая отрасль математики и физики, не зная их основ ты взялся кодить ?
Смеши дальше.
Как известно, миллион обезьян за миллион лет тыкая в клавиши пиш.машинок теоретически могут повторить книгу "Война и мир".
Пробуй дальше.
← →
Jeer © (2006-05-05 13:06) [25]
> про какие-то бабки базарит
"Базарят" на базаре "аспирант".
Либо братки, но ты мелковат для них.
Тебе нужен код - мне не помешают деньги.
Честное предложение.
Или ты халявщик ?
Как я сразу не догадался ?
Не знаешь, что бывает халявщикам за наглость и "базар" ?
← →
Wm.DIGGER © (2006-05-05 13:17) [26]Удалено модератором
← →
Wm.DIGGER © (2006-05-05 13:31) [27]
про какие-то бабки базарит
"Базарят" на базаре "аспирант".
Либо братки, но ты мелковат для них.
Тебе нужен код - мне не помешают деньги.
Честное предложение.
Или ты халявщик ?
Как я сразу не догадался ?
Не знаешь, что бывает халявщикам за наглость и "базар" ?
ох, боже ...
кажется я начинаю понимать ...
я говорю с подростком ...
другого объяснения каких-то глупых угроз и выссказываний просто нет ...
а если это не так и ваш возраст указан верно ...
видимо это называется другим словом :)
p.s. кстати, а уже давно защитился ... так что завязывай(те) с "аспиратном" ... :)
← →
Jeer © (2006-05-05 14:19) [28]Wm.DIGGER © (05.05.06 13:31) [27]
> а уже давно защитился ...
Вообще-то сомневаюсь, ты обитаешь на игровых форумах - "кандидат".
Впрочем, цена многим современным диссерам - ломанный грош.
Я тоже защитился, только намного раньше.
Более того, много лет работал именно в области DSP (цифровая обработка сигналов)
Однако с моей защиты дивиденды были и будут, а с твоей - не видно,
разве, что кроликов ты разводил в своем диссере.
> я хотел только реализовать уже имеющийся, заметь простейший
> вариант!
Значит ты вообще ничего не понимаешь в той области куда пытаешься влезть.
Тем более надо начать с чтения литературы и тематических сайтов.
Как тебе будет заява "кроликовода" - решил, дескать по быстрому построить маленькую атомную станцию на своем кролико-городе.
Подскажите мне самый простейший вариант и желательно изготовьте.
"За парту"
← →
Wm.DIGGER © (2006-05-05 14:33) [29]Удалено модератором
← →
Wm.DIGGER © (2006-05-05 14:54) [30]Удалено модератором
← →
Wm.DIGGER © (2006-05-05 15:08) [31]Удалено модератором
← →
Jeer © (2006-05-05 15:26) [32]Wm.DIGGER © (05.05.06 15:08) [31]
Удачи !
Кроликовод-кандидат.
Посмешил еще раз.
← →
Wm.DIGGER © (2006-05-05 15:38) [33]Удалено модератором
← →
Сергей М. © (2006-05-05 15:43) [34]
> Wm.DIGGER © (05.05.06 13:31) [27]
> я говорю с подростком
Вот засранствовать, "аспирант", явно не в твоих интересах, если ты хочешь реальной помощи.
А ее в виде кода не будет, пока ты либо не прекратишь засранские выапды либо не обозначишь сумму за реализацию того самого якобы "готового" алгоритма, который ты в силу аспирантского развития своего мозжечка не можешь реализовать самостоятельно.
И, умоляю тебя, пацанствуй в подворотне, а не здесь.
← →
Wm.DIGGER © (2006-05-05 16:40) [35]Удалено модератором
Примечание: MAT RO на 3 дня, для начала
← →
Jeer © (2006-05-05 17:06) [36]Держи алгоритм, кролик.
А на твои пацанские привычки всем здесь наплевать.
Подонком был, им же и будешь.
Будешь упорсттвовать дальше - запущу процесс твоей идентификации.
Это легче сделать, чем ты думаешь.
Сделаю это через официальный запрос администрации твоего региона.
Дальше провайдер, анкетные данные, милиция..
Могут быть неофициальные и продолжения этой истории.
function [S] = vocoder(E,Nfft,over,alpha)
% Phase vocoder time-scaling :
% - E : input vector
% - Nfft : size per frame
% - over : overlapp ( between 0 et 1 )
% - alpha : time-expansion/compression factor ( alpha < 1 : compression; alpha > 1 : expansion ).
%
%===================================================================%
% The synthesis signal"s length isn"t exactly alpha*input"s length. %
%===================================================================%
% Verifiy the overlapp
if( over < 0 | over >= 1 )
error("error : overlapp must be between 0 and 1");
end;
if ( alpha <= 0)
error("alpha must be strictly positive");
end;
E = E(:);
N = length(E);
Nfft = 2^(nextpow2(Nfft));
% Computing vocoder"s parameters :
% - La : number of samples to "advance" for each anamysis frame : analysis hop size.
% - nb_frames : number of frames to compute
% - Ls : number of samples ot "advance" for each synthesis frame : synthesis hop size.
% - S : S is the result vector
% - h : hanning window
La = floor((1-over) * Nfft);
nb_frames = floor((N-Nfft) / La);
max = (nb_frames-2)*La + Nfft;
ls = floor(alpha * La);
S = zeros(floor(max*alpha),1);
h = hanning(Nfft);
% Init process :
X = h.*E(1:Nfft);
tX = fft(X,Nfft);
Phis1 = angle(tX)
Phia1 = Phis1;
for loop=2:nb_frames-1
%===============================================================================
% ( classic analysis part of a phase vocoder )
% Take a frame, and windowing it
X = h.*E((loop-1) * La + 1:(loop-1)*La + Nfft);
% XI is the amplitude spectrum, and Phia2 the phase spectrum.
tX = fft(X, Nfft);
Xi = abs(tX);
Phia2 = angle(tX);
%================================================================================
% the part which actually does the time scaling
% One compute the actual pulsations, and shift them. The tricky part is here...
omega = mod( (Phia2-Phia1)-2*pi*([0:Nfft-1].")/Nfft * La + pi, 2*pi) - pi;
omega = 2 * pi * ([0:Nfft-1].") / Nfft + omega / La;
Phis2 = Phis1 + lss_frame*omega;
% The new phases values :
Phis1 = Phis2;
Phia1 = Phia2;
%==============================================================================
% Synthetise the frame, thanks to the computed phase and amplitude spectrum :
% ( classic synthetisis part of a phase vocoder )
tfs = Xi.*exp(j*Phis2);
Xr = real(ifft(tfs)).*h;
% overlapp-add the synthetised frame Xr
S((loop-1)*lss_frame+1:(loop-1)*lss_frame+Nfft) ...
= S((loop-1)*lss_frame+1:(loop-1)*lss_frame+Nfft) + Xr;
end;
← →
Хозяин (2006-05-05 17:33) [37]Wm.DIGGER ©
Хотите победить в перебранке или решить задачу?
Страницы: 1 вся ветка
Форум: "Media";
Текущий архив: 2006.12.17;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.039 c