purebasic.info

PureBasic forum
Текущее время: Пн дек 10, 2018 6:48 pm

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 17 ]  На страницу Пред.  1, 2
Автор Сообщение
 Заголовок сообщения: Re: Ресэмплинг
СообщениеДобавлено: Пн ноя 19, 2018 5:52 pm 
Не в сети
профессор

Зарегистрирован: Вс июл 05, 2009 5:55 pm
Сообщений: 336
Благодарил (а): 1 раз.
Поблагодарили: 11 раз.
Пункты репутации: 0
SereZa по моему, твоя теория не состоятельна. :roll:
вот несколько прог и косяков, там ты сможеш понять почему твой звук кривоват получился:
Цитата:
...кипятком от восторга. правда я не был уверен что сделал все правильно, так как после конвертации звук был с каким-то металлическим призвуком.

Согласно той википедии https://ru.wikipedia.org/wiki/Передискретизация нужно сначала переделать фильтром, а потом делать выборки.
Вот пример с картинкой, скажеш причем звук до картинки, а в той самой вики это тож упоминается и картинки есть, я просто на пурике приведу код демонстрирующий этот эффект.

Вот картинка https://upload.wikimedia.org/wikipedia/ ... -moire.png, и результат внизу слева кривой это твой метод преобразования, нужно сделать увеличение и уменьшение пропорционально как это сказано в вики. Либо использовать при прорисовке строки например в 2 раза уменьшая брать 2 паралельных пикселя и в переди тоже два, суммировать и делить на 4 получим то что нужнопередвигаемся чере пиксель на следующую, ну вобщем получаем чемто похоже на розмытие, но не совсем.

вот мой код
*СЛЕВА ОРИГИНАЛЬНАЯ картинка.
*ПО СРЕДИНЕ ПРАВИЛЬНЫЙ РЕСАЙЗ, он использует фильтр с учетом соседних пикселей, поэтому картинка неискажена.
*СПРАВА НЕ ВЕРНЫЙ РЕСАЙЗ, ТУТ МОЖНО ЗАМЕТИТЬ ИСКАЖЕНИЕ ИЗОБРАЖЕНИЕ
это самй быстрый ресайз, он использует для 50*50 пикселей через строчную выборку и через пиксельную.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
OpenWindow(0,100,150,350,250,"Cre",#PB_Window_SystemMenu) 
 
CreateImage(1,101,101); создаем картинку
 
If StartDrawing(ImageOutput(1)); рисуем круги
    FillArea(10, 10, RGB(250,250,250))
    DrawingMode(#PB_2DDrawing_Outlined  )
    For r=0 To 50 Step 4
        Circle(50,50,r,RGB(150,150,10))
    Next
StopDrawing()
EndIf
 
; создаем несколько копий и ресайзим с фильтром и без
CopyImage(1,2):ResizeImage(2,75,75, #PB_Image_Smooth)
CopyImage(1,3):ResizeImage(3,75,75, #PB_Image_Raw)
 
CopyImage(1,4):ResizeImage(4,50,50, #PB_Image_Smooth)
CopyImage(1,5):ResizeImage(5,50,50, #PB_Image_Raw)
 
; отображаем все это безобразие
ImageGadget(1,0  ,0,100,100,ImageID(1))
 
ImageGadget(2,110,0,100,100,ImageID(2))
ImageGadget(3,220,0,100,100,ImageID(3))
 
ImageGadget(4,110,110,100,100,ImageID(4))
ImageGadget(5,220,110,100,100,ImageID(5))
 
  Repeat
    EventID=WaitWindowEvent()
  Until EventID=#PB_Event_CloseWindow
 
 



ну и везде говорится об преобразовании через фильтра
Сверху — исходный сигнал.
В середине — этот же сигнал после фильтрации в цифровом фильтре нижних частот.
Снизу — децимированный сигнал.

Процесс уменьшения частоты дискретизации сигнала называется децимацией.
Интерполяцией называют увеличение частоты в целое или дробное число ра

Комбинация интерполяции и децимации.
....например, при передискретизации звукового сигнала с 44100 Гц до 48000 Гц этим методом необходимо увеличить частоту дискретизации в 160 раз до 7056000 Гц и затем уменьшить её в 147 раз до 48000 Гц.

Далее сделаем АНИМАЦИЮ, синие линии показывают реальную волну звука(да какая разница чего), по началу все ОК, а потом то что называются приколами и фокусами
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
OpenWindow(0,100,200,700,600,"Create Beizer Curve",#PB_Window_SystemMenu) 
 
st=4; это шаг деления по координате x
; period=st* 20; ну если очень грубо, то так выглядит 20 000 звука на выборке 48 000 дискретизации
period=st* 89/8; это минимальные требования для какогото качества сигнала, почти повторяет форму сигнала, 89 использую чтоб бегало по синусу, а не стояло
 
 
If StartDrawing(WindowOutput(0))
    FrontColor(RGB(10,10,10))
    LineXY(0,200,650,200); ось икс
    LineXY(90,10,90,400); вертикальная
    LineXY(0,291,650,291)
 
    f3=00:xx3=0:yy3=200
   
    For x=0 To 2500; :Delay(1)
        ;Plot(200-Sin(Radian(x ) )*90, Cos(Radian(x ) )*90+200, RGB(200,10,10 ) ); это верно
        Plot(x/st , Cos(Radian(x+90 ) )*90+200, RGB(150,50,50 ) ); рисуем "синус", волну звука
       
        If f3>=period; 190
            Circle(x/st,Cos(Radian(x+90 ) )*90+200,2 ,RGB(20,10,200 ) ); отметим точки выборок
            ;Box(x/st,Cos(Radian(x+90 ) )*90+200,2,2, RGB(20,10,200 ))
            LineXY(x/st,200,x/st,Cos(Radian(x+90 ) )*90+200, RGB(20,10,200 ))
            LineXY(xx3,yy3,x/st, Cos(Radian(x+90 ) )*90+200, RGB(15,10,200 ))
            xx3=x/st:       yy3=Cos(Radian(x+90 ) )*90+200
            f3=0
        EndIf
        f3+1
       
        ;Plot(x+200, Cos(Radian(x ) )*90+200, RGB(10,10,200 ) )
    Next
StopDrawing()
EndIf
 
Repeat
    ;{- этот кусок можно закоментировать и работать с
    period=st* iii:iii+1: If iii>300: iii=1:EndIf
    If StartDrawing(WindowOutput(0))
        Box(0,0,660,550,RGB(200,200,200 ))
    FrontColor(RGB(10,10,10))
    LineXY(0,200,650,200); ось икс
    LineXY(90,10,90,400); вертикальная
    LineXY(0,291,650,291)
 
    f3=00:xx3=0:yy3=200
   
    For x=0 To 2500; :Delay(1)
        ;Plot(200-Sin(Radian(x ) )*90, Cos(Radian(x ) )*90+200, RGB(200,10,10 ) ); это верно
        Plot(x/st , Cos(Radian(x+90 ) )*90+200, RGB(150,50,50 ) ); рисуем "синус", волну звука
       
        If f3>=period; 190
            Circle(x/st,Cos(Radian(x+90 ) )*90+200,2 ,RGB(20,10,200 ) ); отметим точки выборок
            ;Box(x/st,Cos(Radian(x+90 ) )*90+200,2,2, RGB(20,10,200 ))
            LineXY(x/st,200,x/st,Cos(Radian(x+90 ) )*90+200, RGB(20,10,200 ))
            LineXY(xx3,yy3,x/st, Cos(Radian(x+90 ) )*90+200, RGB(15,10,200 ))
            xx3=x/st:       yy3=Cos(Radian(x+90 ) )*90+200
            f3=0
        EndIf
        f3+1
       
        ;Plot(x+200, Cos(Radian(x ) )*90+200, RGB(10,10,200 ) )
    Next
StopDrawing()
EndIf
   
Delay(10+(300-iii))
;}
Delay(1)
    EventID=WindowEvent()
Until EventID=#PB_Event_CloseWindow



Тут можно заметить как реальная выходная частота резко отличается от исходной при дискретизации близкой к исходной и больше неё

вот можно потренироваться там есть опись и можно розкоментировать нужную строку и смотреть резщультат.

; рекомендовано для нормального отображения сигнала иметь более 8 выборок га частоту т. е. F*8
; при частоте звука 20 000 надо 160 000 выборок,
; для уха это не нужно и достаточно 10 000 герц после чего идут искажения незаметны на слух.
; 10 000*8= 80 000 выборок.
; при 20 000 нужно чтобы сигнал хоть както отражал действительность не менее в 2 раза
; вот и получаем 40 000 и чуть выше 44 000 и 48 000, звуковухи могут давно 96 000 выборок в сек.
; но для осциллографа при этом все что выше 96 000/8=8625 герц выглядит как треугольниками.
;
; Даная прога показывает как изменяется результат даныех в зависимости от количества выборок.
; Сюда входит несколько приколов искривления формы сигнала.

Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
OpenWindow(0,100,200,700,600,"Create Beizer Curve",#PB_Window_SystemMenu) 
 
st=4; это шаг деления по координате x
 
;МЕНЯТЬ СЛЕДУЕТ В ЭТОЙ ФОРМУЛЕ, 90 это период совпадает с частотой, При 180 1 выборка на 2 Гц.
;period= это период времени через который нужно сделать выдорку, для точного пересчета на время, нужно формулы.
 
; period=st*90; 1 на герц, выборка равна частоте
;
; period=st*180; 1 выборка на 2 Гц
; period=st*45; 2 выборки на 1 Гц
;
; period=st* 20; ну если очень грубо, то так выглядит 20 000 звука на выборке 48 000 дискретизации
period=st* 89/8; это минимальные требования для какогото качества сигнала, почти повторяет форму сигнала, 89 использую чтоб бегало по синусу, а не стояло
; period=st* 6; это очень хорош результат
; period=st* 2; через пиксель, идеал
; period=st* 1; каждый пиксель, супер
 
;- ;ПРОЙДЕМСЯ ПО ПРИКОЛАМ. Смотрим выходную форму сигнала по синей линии
; period=st*46; 2 выборки на 1 Гц, ну почти, чтобы видеть результат, тут прикол= реально форма звука идеальна, а через неверный выбор выборок исказилось, как наростающий по амплитуде.
; period=st*40; 1 на герц, выборка чаще частоты, прикол пульсирующие частоты, т. е. две.
; period=st* 60; ВОТ ПОЛУЧИМ на выходе частоту(по форме сигнала) в 2 раза меньше, хотя выборок кажется достаточно.
; period=st* 80; вот тут то что ты называеш выборкой с уменьшеной частотой, форму сигнала видиш как частота уменьшена
; period=st* 85; а тут савсем в несколько раз выход поехал
; period=st* 188; ну и в таком духе
 
If StartDrawing(WindowOutput(0))
    FrontColor(RGB(10,10,10))
    LineXY(0,200,650,200); ось икс
    LineXY(90,10,90,400); вертикальная
    LineXY(0,291,650,291)
    f3=00:xx3=0:yy3=200
   
    For x=0 To 2500; :Delay(1)
        Plot(x/st , Cos(Radian(x+90 ) )*90+200, RGB(150,50,50 ) ); рисуем "синус", волну звука
        If f3>=period; 190
            Circle(x/st,Cos(Radian(x+90 ) )*90+200,2 ,RGB(20,10,200 ) ); отметим точки выборок
            LineXY(x/st,200,x/st,Cos(Radian(x+90 ) )*90+200, RGB(20,10,200 ))
            LineXY(xx3,yy3,x/st, Cos(Radian(x+90 ) )*90+200, RGB(15,10,200 ))
            xx3=x/st:       yy3=Cos(Radian(x+90 ) )*90+200
            f3=0
        EndIf
        f3+1
    Next
StopDrawing()
EndIf
 
Repeat
    EventID=WaitWindowEvent()
Until EventID=#PB_Event_CloseWindow


Вобщем без фильтров никак :roll:
А на высоких частотах еще и востановить оригинальный синус, это я про то каким это образм сделать. Смотрел про три точки, нето, нужно как минимум сплайны(кривые), тот код что я давал, и еще учитывать соседние как направляющие.
Если синус то между двух выборок делать соединение и расчитывать дугу в зависимости од предыдущего направление для первой части и второй части зависит од того что после идет.
Другими словами, если поставить на синусе вверху выборку и в самом низу, место соединения по средине.
То можно увидеть что первая дуга выпукла вверх, а после средины выпукла вниз, и это определяет для первой дуги предыдущая высота, а для второй дуги следующая выборка.
Вожможно нужно проганять маятником и вычислять направленость.

Вобщем проще нарисовать, чем на пальцах.
Сплайны годятся но их по заумным :? формулам нужно вычислять, а потом рисовать чтобы видеть что твориться в реальности :)
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
OpenWindow(0,100,200,700,600,"Create Beizer Curve",#PB_Window_SystemMenu) 
G=RGB(0,250,0)
If StartDrawing(WindowOutput(0))
    FrontColor(RGB(10,10,10))
    LineXY(0,200,650,200); ось икс
    LineXY(90,10,90,400) ; вертикальная
    LineXY(270,10,270,400) ; вертикальная
   
    LineXY(0,291,650,291)
    Circle(90,110,3,RGB(20,10,200 ) ):DrawText(70,90,"первая выборка", RGB(255, 255, 255))
     Circle(270,290,3,RGB(20,10,200 ) ):DrawText(250,300,"вторая выборка", RGB(255, 255, 255))
     LineXY(180,10,180,400); вертикальная
     
     LineXY(140,140,400,140,g):DrawText(400,140,"изгиб вверх", g)
     LineXY(210,240,400,240,g):DrawText(400,240,"изгиб вниз", g)
     
    For x=0 To 360; :Delay(1)
        Plot(x , Cos(Radian(x+90 ) )*90+200, RGB(150,50,50 ) ); рисуем "синус", волну звука
 
    Next
StopDrawing()
EndIf
 
Repeat
    EventID=WaitWindowEvent()
Until EventID=#PB_Event_CloseWindow


_________________
искатель истины


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Ресэмплинг
СообщениеДобавлено: Вт ноя 20, 2018 3:13 am 
Не в сети
профессор

Зарегистрирован: Пт фев 20, 2009 12:57 pm
Сообщений: 1717
Откуда: Алматы
Благодарил (а): 16 раз.
Поблагодарили: 47 раз.
Пункты репутации: 5
ну это чото как-то сложно :) не поленился взял сэмпл моно 8бит 16кгц и отконвертил его в 11025кгц в своем конвертере и в каком-то там нормальном. они так на скрине и идут - 16 первый изначальный, 10000 - но на самом деле там 11025 просто в моем конвертере и 11025 в нормальном конвертере. сетка правда скачет, что портит картину... как зафиксировать сетку в старом кулэдите не нашел. всех троих в одну линию тоже не дает выставлять. ругается дескать это разная частота.

Изображение

однако 16к и мой конверченный очень даж друг на друга похожи :) так что результатом я доволен, не смотря на всякие фильтры, переумножение куда-то там и сложные перерасчеты. ну и поскольку мой целевой формат это в основном 10400кгц и меньше, то особого качества там не требуется, уж тем более что проигрываться будет либо на приставках, либо на эмуляторе. впрочем меня смущает громкость. оригинальные сэмплы звучать довольно прилично. моя же писанина, если речь идет про голос - звучит довольно тихо. саму громкость я пытался приделать. но что-то не очень получается :) по 0.1 или 0.2 чтоль там шаг. в результате после пары делений появляются хрипы. хорошо бы там тоже чо подумать... но это уже другая история :) мы тут частоту обсуждаем.


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 17 ]  На страницу Пред.  1, 2

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB