http://kin.naver.com/detail/detail.php?d1id=11&dir_id=110209&eid=vwwQXehdxE9+5o6Q3l15DrPlcSGIAR/q&qb=x9i51iDH2LTX&pid=f6Y67woi5UZssZmMFOVsss--421733&sid=SKvJBB6zq0gAAFd5Y3k
디지털필터에 사용되는 창함수는 왜 쓰며, 해밍, 해닝,카이저등 각각의 차이점은 뭔가요??
창함수의 컨셉은 같은 이야기지만 다른각도로서..
하나는 신호를 구간화하기 위해 사용되는것이며..
다른 의미로 일종의 필터링입니다.
위에서도 말했지만 사실 두가지의미는 하나를 의미합니다.
보통 DSP에서는 FIR필터를 설계할때를 예로들어 윈도를 설명합니다.
왜?
컨벌루션이라는 연산을 DSP가 해주도록 해야하기 때문입니다.
컨벌루션은 쉽게 시스템의 전달함수와 신호자체를 가지고선
하나를 뒤집어서 -무한대에서 +무한대 까지 곱하여 각각을 더한후 시간축에
나열하는 연산입니다.
이 연산의 결과는 그 시스템에 그 신호를 유입시켰을때 출력되는 파형이 됩니다.
시스템과 신호의 측면뿐아니라 모든 시간축파형의 곱은 컨벌루션이란 연산에의해
결과를 볼수있습니다.
그런데 여기서 연산의 구간이 -무한대에서 +무한대입니다.
그러니 시스템과 신호가 둘다 무한대라면
컨벌루션이 무한대로 계속연산하는 것이라서 출력을 영원히 보지못할겁니다.^^
결과를 모두 합쳐야 하는데 결과가 끝이없으니까요..
그래서 컨벌루션이라는 연산은 실제로 구현시 신호나 시스템 둘중 하나는 유한하게
만들어야 합니다. 그렇다면 실제로 사용되는 시스템을 생각해봅시다
당연히 신호를 유한화 시킬수 없는거 아니겠습니까?
시스템을 유한화 시켜야지요..
그래서 결국은 시스템은 자신의 창을 가지고 연속된 신호를 창의 구간으로
나누어 봅니다. 그러면 나머지 창 바깥에 있는 신호는 무시하는 것이죠.
이렇게 되면 무한한 연산의 구간이 창함수에 의해 제한되어 유한한 연산으로
바뀌기 때문입니다 나머지는 0이니까 계산안하게 하고 말이죠..
그러니 윈도우를 신호에 씌우게 됩니다. 결국은 시스템이 윈도우를 통해서
무한한 신호를 바라보는 것이죠
그러면서 신호는 창으로 지나갑니다.
기차를 타면 창을 통해 풍경이 지나가죠? 창틀바깥에 있는 풍경은 벽에 가려
보이지 않습니다. 그것을 연상하면 됩니다.
이런식으로 풍경이 조금 변할때마다 새로운 연산이 시작되겠죠?
다음번 컨벌루션과 계속 합쳐나가면 신호를 연속해서 본것과 비슷할거라는
생각을 할수 있습니다. 하지만 결코 똑같지는 않습니다.
창의 종류는 여기서 나타납니다.
왜 똑같지 않는가?
시간축의 사각형창은 주파수축으로 가져가보면 Sinc함수가 되서 무한대의 값을
가집니다. 아무리 크기가 작아도 이 무한대성분을 모두 고려해야만
원래신호를 그대로나타내는겁니다. 하나라도 빠지면 수학적으로 둘은 같은
신호가 아닌것이죠..
자.. 뭐랑 똑같습니까? 이상적인 LPF를 만들수 없다.. 와 일맥상통하죠?
그래서 주파수축에서 짤라버리면 다시 시간축으로 바꿀때
정확히 사각형의 창이 될까요?
휘어지죠? 휘어진 창으로 풍경을 보니 풍경이 달라보일밖에요..
그래서 창함수들이 연구된겁니다.
어떻하면 이상적인 시간축에서의 사각형을 만들것이냐..
결국..이것이 이상적인 LPF를 만드는것이 된것이죠...
이걸 연구한 사람들이 해밍 해닝 블랙맨..이란 사람들입니다.
자신의 이름이 창의 이름이 된것이죠^^ 앞으로 DSP하는사람들은 모조리
자기 이름을 한번씩 부르게 되어있겠죠? ^^
그중 카이저란 사람이 제안한 창함수가 가장 성능이 탁월하다고 알려져 있습니다.
그런데 왜 해밍창을 많이 쓰느냐? 간단하니까요^^ 연산시간이 오래걸리지 않다는
의미니까요..
항상 디지털은 연산량과 성능 사이에서 갈등하고 있는겁니다.^^
도움이 되셨길 빌며
http://en.wikipedia.org/wiki/Window_function
http://en.wikipedia.org/wiki/Short-time_Fourier_transform
http://en.wikipedia.org/wiki/Short-time_Fourier_transform#Resolution_issues
http://www.captain.at/howto-fftw-spectrograph.php
http://www.gpgstudy.com/forum/viewtopic.php?t=6155&highlight=gdi%2B
GDI+를 이용해 몇가지 프로그램을 짜봤습니다.(C#과 Managed C++에서...)
결론만 말씀드리자면... 무지 느립니다..ㅡㅡ;; 실시간 처리 환경에서는 완전 비추입니다.
그렇지만 지금 GDI+를 사용해서 득을 볼 수 있는 가장 큰 장점은 그래픽파일을 다루는 부분일겁니다. 대표적으로 에니메이션gif를 지원하기 땜시롱 이를 DX와 잘 연동시킨다면 스프라이트툴을 따로만들필요가 없다는..
http://blog.naver.com/sang980/120011050112
Win32GDI 점, 선, 면 찍기
그래프 그리기
1. Bitmap 객체 생성
Bitmap b = new Bitmap(100,100);
2. Bitmap에다가 점을 찍던 SetPixel, 선을 긋던 DrawLine, 사각형을 그리던 해서 그린다.
b.SetPixel(50,50,Color.White);
또는
Graphics g = Graphics.FromImage(b);
g.DrawLine(~~~);
3. PictureBox.Image = b;
끝
http://blog.naver.com/dunyazad/150031941625
http://paranbaram.springnote.com/pages/941968
MCI는 win32에서 제공하는 Multimedia Control Interface의 약자입니다.
C#에서 mciSendString을 쓰려면 "winmm.dll"을 import 해야합니다. 과제를 내주신 선배님은 DLLImpport가 바람직한 것은 아니라고 하셨어요. 하지만 Framework 2.0이 제공하는 것도 한계가 있다보니, 필요한 것은 import 해서 쓸 수 있도록 되어있습니다.
http://msdn.microsoft.com/en-us/library/ms713277(VS.85).aspx
MCI 명령어들
http://www.xtremevbtalk.com/showthread.php?t=171130&highlight=midi+getshortpathname
My MCIMIDI class
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "MCIMIDI"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
'
' MCIMIDI Class Module
' By Joseph Koss in 2004
'
' Properties:
'
' Volume Gets/Sets the volume for both channels (0..65535)
' LVolume Gets/Sets the left channel volume (0..65535)
' RVolume Gets/Sets the right channel volume (0..65535)
'
' Methods:
'
' OpenFile(FileName) Loads the given MIDI file into MCI, returns 0 on success
' CloseFile() Closes the currently open file, returns 0 on success
' File() Returns the filename of the most recently loaded song (path stripped)
'
' Play() Plays the currently loaded file, returns 0 on success
' PlayFrom(T) Plays from position T (in milliseconds) returns 0 on success
' StopPlay() Stops playback returns 0 on success
'
' Position() Returns the current position (in milliseconds)
' Length() Returns the song length (in milliseconds) - Known to not always be accurate due to tempo changes.
' Status() Returns the MCI status string ("playing", "stopped", etc..)
'
' ErrString(ErrCode) Returns a description of an MCI error
'
' Notes:
'
' Volume is not changed using MCI commands, volume is changed through WINMM.DLL low
' level midi api and may not work on external synths
'
Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
Private Declare Function mciGetErrorString Lib "winmm.dll" Alias "mciGetErrorStringA" (ByVal dwError As Long, ByVal lpstrBuffer As String, ByVal uLength As Long) As Long
Private Declare Function mciGetDeviceID Lib "winmm.dll" Alias "mciGetDeviceIDA" (ByVal lpstrName As String) As Long
Private Declare Function midiOutSetVolume Lib "winmm.dll" (ByVal uDeviceID As Long, ByVal dwVolume As Long) As Long
Private Declare Function midiOutGetVolume Lib "winmm.dll" (ByVal uDeviceID As Long, lpdwVolume As Long) As LongPrivate Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
Option Explicit
Private myFile As String
' ---
Public Function OpenFile(filename As String) As Long
myFile = GetFileName(filename)
OpenFile = mciSendString("open " & GetShortName(filename) & " type sequencer alias MCIMIDI", 0&, 0, 0)
End FunctionPublic Function CloseFile() As Long
CloseFile = mciSendString("close MCIMIDI", 0&, 0, 0)
End FunctionPublic Function File() As String
File = myFile
End Function' ---
Public Function Play() As Long
Dim ret As Long
ret = mciSendString("set MCIMIDI time format milliseconds", 0&, 0, 0)
Play = mciSendString("play MCIMIDI", 0&, 0, 0)
End FunctionPublic Function PlayFrom(ms As Long) As Long
Dim ret As Long
ret = mciSendString("set MCIMIDI time format milliseconds", 0&, 0, 0)
PlayFrom = mciSendString("play MCIMIDI from " & ms, 0&, 0, 0)
End FunctionPublic Function StopPlay() As Long
StopPlay = mciSendString("stop MCIMIDI", 0&, 0, 0)
End Function' ---
Public Function Position() As Long
Dim ret As Long
Dim s As String, slen As Long
slen = 1024
s = Space(slen)
ret = mciSendString("status MCIMIDI position", s, slen, 0)
Position = Val(AsciiZ(s))
End FunctionPublic Function Length() As Long
Dim ret As Long
Dim s As String, slen As Long
slen = 1024
s = Space(slen)
ret = mciSendString("status MCIMIDI length", s, slen, 0)
Length = Val(AsciiZ(s))
End Function' ---
Public Function Status() As String
Dim ret As Long
Dim s As String, slen As Long
slen = 1024
s = Space(slen)
ret = mciSendString("status MCIMIDI mode", s, slen, 0)
Status = AsciiZ(s)End Function
' ---
Public Property Get volume() As Long
Dim L As Long, R As Long
L = LVolume
R = RVolume
volume = (L + R) \ 2
End PropertyPublic Property Let volume(v As Long)
LVolume = v
RVolume = v
End PropertyPublic Property Get LVolume() As Long
Dim v As Long, ID As Long, ret As Long
ID = mciGetDeviceID("MCIMIDI")
ret = midiOutGetVolume(ID, v)
LVolume = v And &HFFFF&
End PropertyPublic Property Let LVolume(v As Long)
Dim vv As Long, ID As Long, ret As Long
ID = mciGetDeviceID("MCIMIDI")
ret = midiOutGetVolume(ID, vv)
ret = midiOutSetVolume(ID, (vv And &HFFFF0000) Or (v And &HFFFF&))
End PropertyPublic Property Get RVolume() As Long
Dim v As Long, ID As Long, ret As Long
ID = mciGetDeviceID("MCIMIDI")
ret = midiOutGetVolume(ID, v)
RVolume = ((v And &HFFFF0000) \ &H10000) And &HFFFF&
End PropertyPublic Property Let RVolume(v As Long)
Dim vv As Long, ID As Long, ret As Long
ID = mciGetDeviceID("MCIMIDI")
ret = midiOutGetVolume(ID, vv)
If v And &H8000 Then
ret = midiOutSetVolume(ID, (vv And &HFFFF&) Or (&H10000 * (v And &H7FFF&)) Or &H80000000)
Else
ret = midiOutSetVolume(ID, (vv And &HFFFF&) Or ((v * &H10000) And &HFFFF0000))
End If
End Property
Public Function ErrString(ErrCode As Long) As String
Dim ret As Long, s As String, slen As Long
slen = 1024
s = Space(slen)
ret = mciGetErrorString(ErrCode, s, slen)
ErrString = AsciiZ(s)
End FunctionPrivate Sub Class_Terminate()
StopPlay
CloseFile
End Sub
' -------------------------------------------------------------------------------------------------Private Function GetShortName(ByVal sLongFileName As String) As String
Dim lRetVal As Long, sShortPathName As String, iLen As Integer
sShortPathName = Space(1024)
iLen = Len(sShortPathName)
lRetVal = GetShortPathName(sLongFileName, sShortPathName, iLen)
GetShortName = Left(sShortPathName, lRetVal)
End FunctionPrivate Function GetFileName(ByVal filename As String) As String
Dim i As Long, j As Long
i = InStrRev(filename, "/")
j = InStrRev(filename, "\")
If j > i Then i = j
GetFileName = Mid(filename, i + 1)
End FunctionPrivate Function AsciiZ(ByVal s As String) As String
' truncates a string at the first nul character
Dim i As Long
i = InStr(s, Chr$(0))
If i Then
AsciiZ = Left(s, i - 1)
Else
AsciiZ = s
End If
End Function
http://ccrma.stanford.edu/courses/422/projects/WaveFormat
웨이브 파일 포맷이 나와있다.
http://www.codeproject.com/KB/audio-video/cswavplay.aspx
A low-level audio player in C#
바이트 단위로 읽어들이기.
여기서 16bit = short 단위로 들어있다면
-32768 ~ 32767 의 값이 들어있다.
이 값을 -1 ~ 1 로 바꾼다. (float이나 double로)
http://www.codeproject.com/KB/audio-video/SoundViewer.aspx
Sound visualizer in C#
이 값을 화면에 표시하려면
그냥 파동만 표시하는 건 그대로 찍어주면 된다.
energy를 표시하려면, 구간 (400개 단위라던가) 을 정하고, 그 구간에서의 최대값과 최소값을 구해서 표시한다.
최대값 = 0 부터 시작, 이보다 큰 값이 있으면 갱신
최소값 = 0 부터 시작, 이보다 작은 값이 있으면 갱신
화면에 표시하려면 GDI+ 사용.